package com.example.javabighw.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.example.javabighw.controller.SessionController;
import com.example.javabighw.entity.User;

@Component
public class UserDao {
    @Value("${databaseUrl}")
    String databaseUrl;

    @Value("${databaseUser}")
    String databaseUser;

    @Value("${databaseUserPassword}")
    String databaseUserPassword;

    public boolean createUser(User user) {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            Connection conn = DriverManager.getConnection(databaseUrl, databaseUser, databaseUserPassword);
            // TODO: add VALID session_key field
            String sql = "INSERT INTO user_t (username, password, gitee_access_token, gitee_refresh_token, gitee_avatar_url, gitee_id, session_key) VALUES (?, ?, ?, ?, ?, ?, ?)";
            PreparedStatement preStmt = conn.prepareStatement(sql);
            preStmt.setString(1, user.getUsername());
            preStmt.setString(2, user.getPassword());
            preStmt.setString(3, user.getGiteeAccessToken());
            preStmt.setString(4, user.getGiteeRefreshToken());
            preStmt.setString(5, user.getGiteeAvatarUrl());
            preStmt.setString(6, user.getGiteeId());
            preStmt.setString(7, user.getSessionKey());

            preStmt.execute();
            preStmt.close();
            conn.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return true;
    };

    public boolean createUserFromGitee(String gitee_id,
            String gitee_nickname,
            String gitee_access_token,
            String gitee_refresh_token,
            String gitee_avatar_url) {
        User user = new User();
        user.setGiteeId(gitee_id);
        user.setNickname(gitee_nickname);
        // Use the nickname in gitee as the username
        user.setUsername(gitee_nickname);
        user.setGiteeAccessToken(gitee_access_token);
        user.setGiteeRefreshToken(gitee_refresh_token);
        user.setGiteeAvatarUrl(gitee_avatar_url);
        // Generate a random uuid as the password
        user.setPassword(UUID.randomUUID().toString());
        // TODO: refactor this ugly function
        user.setSessionKey(SessionController.randomSessionKey());

        return this.createUser(user);
    }

    public User getUserBySessionKey(String session_key) {
        User user = new User();
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            Connection conn = DriverManager.getConnection(databaseUrl, databaseUser, databaseUserPassword);
            String sql = "SELECT * FROM user_t WHERE session_key = ?";
            PreparedStatement preStmt = conn.prepareStatement(sql);
            preStmt.setString(1, session_key);

            ResultSet rs = preStmt.executeQuery();
            if (rs.next()) {
                setUserFromResultSet(user, rs);
            } else {
                System.out.println("User not exist...");
            }
            rs.close();
            preStmt.close();
            conn.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return user;
    }

    public User getUserById(String id) {
        User user = new User();
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            Connection conn = DriverManager.getConnection(databaseUrl, databaseUser, databaseUserPassword);
            String sql = "SELECT * FROM user_t WHERE id = ?";
            PreparedStatement preStmt = conn.prepareStatement(sql);
            preStmt.setString(1, id);

            ResultSet rs = preStmt.executeQuery();
            if (rs.next()) {
                setUserFromResultSet(user, rs);
            } else {
                System.out.println("User not exist...");
            }
            rs.close();
            preStmt.close();
            conn.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return user;
    }

    public User getUserByGiteeId(String gitee_id) {
        User user = new User();
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            Connection conn = DriverManager.getConnection(databaseUrl, databaseUser, databaseUserPassword);
            String sql = "SELECT * FROM user_t WHERE gitee_id = ?";
            PreparedStatement preStmt = conn.prepareStatement(sql);
            preStmt.setString(1, gitee_id);

            ResultSet rs = preStmt.executeQuery();
            if (rs.next()) {
                setUserFromResultSet(user, rs);
            } else {
                System.out.println("User not exist...");
            }
            rs.close();
            preStmt.close();
            conn.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return user;
    }

    public User getUserByUsername(String username) {
        User user = new User();
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            Connection conn = DriverManager.getConnection(databaseUrl, databaseUser, databaseUserPassword);
            String sql = "SELECT * FROM user_t WHERE username = ?";
            PreparedStatement preStmt = conn.prepareStatement(sql);
            preStmt.setString(1, username);

            ResultSet rs = preStmt.executeQuery();
            if (rs.next()) {
            } else {
                System.out.println("User not exist...");
            }
            rs.close();
            preStmt.close();
            conn.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return user;
    }

    public boolean deleteUserById(String id) {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            Connection conn = DriverManager.getConnection(databaseUrl, databaseUser, databaseUserPassword);
            String sql = "DELETE FROM user_t WHERE id = ?";
            PreparedStatement preStmt = conn.prepareStatement(sql);
            preStmt.setString(1, id);
            preStmt.executeUpdate();
            conn.close();
            preStmt.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return true;
    }

    public void updateUser(User user) {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            Connection conn = DriverManager.getConnection(databaseUrl, databaseUser, databaseUserPassword);
            String sql = "UPDATE user_t SET password = ?, nickname = ?, gitee_access_token = ?, gitee_refresh_token = ?, session_key = ?, gitee_nickname = ? WHERE id = ?";
            PreparedStatement preStmt = conn.prepareStatement(sql);
            preStmt.setString(1, user.getPassword());
            preStmt.setString(2, user.getNickname());
            preStmt.setString(3, user.getGiteeAccessToken());
            preStmt.setString(4, user.getGiteeRefreshToken());
            preStmt.setString(5, user.getSessionKey());
            preStmt.setString(6, user.getGiteeNickname());
            preStmt.setString(7, user.getId());
            preStmt.executeUpdate();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public boolean isExistByGiteeId(String gitee_id) {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            Connection conn = DriverManager.getConnection(databaseUrl, databaseUser, databaseUserPassword);
            String sql = "SELECT * FROM user_t WHERE gitee_id = ?";
            PreparedStatement preStmt = conn.prepareStatement(sql);
            preStmt.setString(1, gitee_id);

            ResultSet rs = preStmt.executeQuery();
            if (rs.next()) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public boolean isExistBySessionKey(String session_key) {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            Connection conn = DriverManager.getConnection(databaseUrl, databaseUser, databaseUserPassword);
            String sql = "SELECT * FROM user_t WHERE session_key = ?";
            PreparedStatement preStmt = conn.prepareStatement(sql);
            preStmt.setString(1, session_key);

            ResultSet rs = preStmt.executeQuery();
            if (rs.next()) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private void setUserFromResultSet(User user, ResultSet rs) throws SQLException {
        user.setId(rs.getString("id"));
        user.setUsername(rs.getString("username"));
        user.setPassword(rs.getString("password"));
        user.setGiteeId(rs.getString("gitee_id"));
        user.setGiteeAccessToken(rs.getString("gitee_access_token"));
        user.setGiteeRefreshToken(rs.getString("gitee_refresh_token"));
        user.setGiteeAvatarUrl(rs.getString("gitee_avatar_url"));
        user.setSessionKey(rs.getString("session_key"));
        user.setLastTimeFromString(rs.getString("last_time"));
    }
}
